;;
;;FUNCTIONS
;;

(deffunction MAP::distance (?xTo ?yTo ?x ?y)
return (sqrt (+ (** (- ?xTo ?x) 2) (** (- ?yTo ?y) 2)))
)

(deffunction MAP::get-move-y (?y ?dir)
(if (eq ?dir "up")
	then return (- ?y 1)
	else (if (eq ?dir "down")
		then return (+ ?y 1)
		else return ?y
		)
	)
)

(deffunction MAP::get-move-x (?x ?dir)
(if (eq ?dir "left")
	then return (- ?x 1)
	else (if (eq ?dir "right")
		then return (+ ?x 1)
		else return ?x
		)
	)
)

(deffunction MAP::is-near (?x1 ?y1 ?x2 ?y2)
	(if (and (eq ?x1 (+ ?x2 1)) (eq ?y1 ?y2))
		then return "left"
		else (if (and (eq ?x1 (- ?x2 1)) (eq ?y1 ?y2))
			then return "right"
			else (if (and (eq ?x1 ?x2) (eq ?y1 (+ ?y2 1)))
				then return "up"
				else (if (and (eq ?x1 ?x2) (eq ?y1 (- ?y2 1)))
					then return "down"
					else return "false"
				)
			)
		)
	)
)

;;
;;HUMAN RULES
;;

(defrule MAP::find-move-places
	(map-object (id ?id) (type "human") (x ?x) (y ?y))
	(near-empty (id ?id2) (target-id ?id) (direction ?dir))
	=>
	(bind ?hx (get-move-x ?x ?dir))
	(bind ?hy (get-move-y ?y ?dir))
	(assert (move-place ?id "human" ?dir ?hx ?hy))
)


(defrule MAP::eat
	(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
	(map-object (id ?id3) (type "tree") (x ?xt) (y ?yt))
	(test (neq (is-near ?x ?y ?xt ?yt) "false"))
	(test (< ?en 15))
	=>
	;;(printout t (str-cat "WORSE-PATH :") crlf)
	(assert (action (name "replenish") (type "human") (id ?id)))
)


(defrule MAP::run-away-from-zombie
	(declare (salience -3000))
	(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
	(map-object (id ?idz) (type "zombie") (x ?xz) (y ?yz) (energy ?enz))
	(test (< (distance ?x ?y ?xz ?yz) 3.0))
	(test (< ?en ?enz))
	?m <- (move-place ?id "human" ?dir ?hx ?hy)
	(test (< (distance ?hx ?hy ?xz ?yz) (distance ?x ?y ?xz ?yz)))
	=>
	;;(printout t (str-cat "RUN-AWAY-RETRACT : " ?id " " ?dir) crlf)
	(assert (run-away ?id "human"))
	(retract ?m)
)

(defrule MAP::get-trees
	(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
	(test (< ?en 15))
	(map-object (id ?idt) (type "tree") (x ?xTo) (y ?yTo))
	=>
	(bind ?dist (distance ?xTo ?yTo ?x ?y))
	(assert (human-tree ?id ?idt ?dist))
)

(defrule MAP::remove-worse-trees
	(declare (salience -4000))
	?t1 <- (human-tree ?id ?idt ?dist)
	?t2 <- (human-tree ?id ?idt2 ?dist2)
	(test (< ?dist ?dist2))
	=>
	;;(printout t (str-cat "WORSE-TREE : " ?id " " ?dist2 " " ?idt2) crlf)
	;;(printout t (str-cat "OTHER-TREE : " ?id " " ?dist " " ?idt) crlf)
	(retract ?t2)
)

(defrule MAP::remove-worse-tree-paths
	(declare (salience -6000))
	(human-tree ?id ?idt ?dist)
	(not (run-away ?id "human"))
	?m1 <- (move-place ?id "human" ?dir ?hx1 ?hy1)
	?m2 <- (move-place ?id "human" ?dir2 ?hx2 ?hy2)
	(map-object (id ?idt) (type "tree") (x ?xTo) (y ?yTo))
	(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
	(test (< (distance ?xTo ?yTo ?hx1 ?hy1) (distance ?xTo ?yTo ?hx2 ?hy2)))
	=>
	;;(printout t (str-cat "WORSE-PATH : " ?dir2 " " ?id " " ?idt) crlf)
	;;(printout t (str-cat "OTHER-PATH : " ?dir " " ?id " " ?idt) crlf)
	(retract ?m2)
)


(defrule MAP::add-best-move-actions
	(declare (salience -8000))
	(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
	(move-place ?id "human" ?dir ?hx ?hy)
	=>
	;;(printout t (str-cat "TREE2 : " ?dir " " ?id ) crlf)
	(assert (action (name "move") (direction ?dir) (type "human") (id ?id)))
)



;;
;;ZOMBIE RULES
;;

(defrule MAP::find-zombie-move-places
	(map-object (id ?id) (type "zombie") (x ?x) (y ?y))
	(near-empty (id ?id2) (target-id ?id) (direction ?dir))
	=>
	(bind ?hx (get-move-x ?x ?dir))
	(bind ?hy (get-move-y ?y ?dir))
	(assert (move-place ?id "zombie" ?dir ?hx ?hy))
)

(defrule MAP::attack
	(map-object (id ?id) (type "zombie") (x ?x) (y ?y))
	(map-object (id ?idh) (type "human") (x ?xt) (y ?yt))
	(test (neq (is-near ?x ?y ?xt ?yt) "false"))
	=>
	;;(printout t (str-cat "ATTACK : " ?id " " ?idh) crlf)
	(assert (action (name "attack") (type "zombie") (id ?id) (target-id ?idh)))
)

(defrule MAP::get-humans
	(map-object (id ?id) (type "zombie") (x ?x) (y ?y))
	(map-object (id ?idt) (type "human") (x ?xTo) (y ?yTo))
	=>
	(bind ?dist (distance ?xTo ?yTo ?x ?y))
	(assert (zombie-human ?id ?idt ?dist))
)

(defrule MAP::remove-worse-humans
	(declare (salience -4000))
	?t1 <- (zombie-human ?id ?idt ?dist)
	?t2 <- (zombie-human ?id ?idt2 ?dist2)
	(test (< ?dist ?dist2))
	=>
	;;(printout t (str-cat "WORSE-HUMAN : " ?id " " ?dist2 " " ?idt2) crlf)
	;;(printout t (str-cat "OTHER-HUMAN : " ?id " " ?dist " " ?idt) crlf)
	(retract ?t2)
)

(defrule MAP::remove-worse-human-paths
	(declare (salience -6000))
	(zombie-human ?id ?idt ?dist)
	?m1 <- (move-place ?id "zombie" ?dir ?hx1 ?hy1)
	?m2 <- (move-place ?id "zombie" ?dir2 ?hx2 ?hy2)
	(map-object (id ?idt) (type "human") (x ?xTo) (y ?yTo))
	(map-object (id ?id) (type "zombie") (x ?x) (y ?y) (energy ?en))
	(test (< (distance ?xTo ?yTo ?hx1 ?hy1) (distance ?xTo ?yTo ?hx2 ?hy2)))
	=>
	;;(printout t (str-cat "WORSE-HUMAN-PATH : " ?dir2 " " ?id " " ?idt) crlf)
	;;(printout t (str-cat "OTHER-HUMAN-PATH : " ?dir " " ?id " " ?idt) crlf)
	(retract ?m2)
)

(defrule MAP::add-best-zombie-actions
	(declare (salience -8000))
	(map-object (id ?id) (type "zombie") (x ?x) (y ?y) (energy ?en))
	(move-place ?id "zombie" ?dir ?hx ?hy)
	=>
	;;(printout t (str-cat "TREE : " ?dir " " ?id " " ?dist " " ?idt) crlf)
	(assert (action (name "move") (direction ?dir) (type "zombie") (id ?id)))
)



;;
;;MACHINE RULES
;;

(defrule MAP::find-machine-move-places
	(map-object (id ?id) (type "machine") (x ?x) (y ?y))
	(near-empty (id ?id2) (target-id ?id) (direction ?dir))
	=>
	(bind ?hx (get-move-x ?x ?dir))
	(bind ?hy (get-move-y ?y ?dir))
	(assert (move-place ?id "machine" ?dir ?hx ?hy))
)

(defrule MAP::machine-attack
	(map-object (id ?id) (type "machine") (x ?x) (y ?y))
	(map-object (id ?idh) (type ?type) (x ?xt) (y ?yt))
	(test (or (eq ?type "zombie") (eq ?type "human")))
	(test (neq (is-near ?x ?y ?xt ?yt) "false"))
	=>
	;;(printout t (str-cat "ATTACK : " ?id " " ?idh) crlf)
	(assert (action (name "attack") (type "machine") (id ?id) (target-id ?idh)))
)

(defrule MAP::get-targets
	(map-object (id ?id) (type "machine") (x ?x) (y ?y))
	(map-object (id ?idt) (type ?type) (x ?xTo) (y ?yTo))
	(test (or (eq ?type "zombie") (eq ?type "human")))
	=>
	;;(printout t (str-cat "TARGET : " ?id " " ?idt " " ?type) crlf)
	(bind ?dist (distance ?xTo ?yTo ?x ?y))
	(assert (machine-target ?id ?idt ?dist))
)

(defrule MAP::remove-worse-targets
	(declare (salience -4000))
	?t1 <- (machine-target ?id ?idt ?dist)
	?t2 <- (machine-target ?id ?idt2 ?dist2)
	(test (< ?dist ?dist2))
	=>
	;;(printout t (str-cat "WORSE-TARGET : " ?id " " ?dist2 " " ?idt2) crlf)
	;;(printout t (str-cat "OTHER-TARGET : " ?id " " ?dist " " ?idt) crlf)
	(retract ?t2)
)

(defrule MAP::remove-worse-target-paths
	(declare (salience -6000))
	(machine-target ?id ?idt ?dist)
	?m1 <- (move-place ?id "machine" ?dir ?hx1 ?hy1)
	?m2 <- (move-place ?id "machine" ?dir2 ?hx2 ?hy2)
	(map-object (id ?idt) (type "machine") (x ?xTo) (y ?yTo))
	(map-object (id ?id) (type "machine") (x ?x) (y ?y) (energy ?en))
	(test (< (distance ?xTo ?yTo ?hx1 ?hy1) (distance ?xTo ?yTo ?hx2 ?hy2)))
	=>
	;;(printout t (str-cat "WORSE-TARGET-PATH : " ?dir2 " " ?id " " ?idt) crlf)
	;;(printout t (str-cat "OTHER-TARGET-PATH : " ?dir " " ?id " " ?idt) crlf)
	(retract ?m2)
)

(defrule MAP::add-best-machine-actions
	(declare (salience -8000))
	(map-object (id ?id) (type "machine") (x ?x) (y ?y) (energy ?en))
	(move-place ?id "machine" ?dir ?hx ?hy)
	=>
	;;(printout t (str-cat "TREE : " ?dir " " ?id " " ?dist " " ?idt) crlf)
	(assert (action (name "move") (direction ?dir) (type "machine") (id ?id)))
)

(defrule MAP::get-plants
	(map-object (id ?id) (type "machine") (x ?x) (y ?y) (energy ?en))
	(test (< ?en 15))
	(map-object (id ?idt) (type "plant") (x ?xTo) (y ?yTo))
	=>
	(bind ?dist (distance ?xTo ?yTo ?x ?y))
	(assert (machine-plant ?id ?idt ?dist))
)

(defrule MAP::remove-worse-plants
	(declare (salience -3000))
	?t1 <- (machine-plant ?id ?idt ?dist)
	?t2 <- (machine-plant ?id ?idt2 ?dist2)
	(test (< ?dist ?dist2))
	=>
	;;(printout t (str-cat "WORSE-PLANT : " ?id " " ?dist2 " " ?idt2) crlf)
	;;(printout t (str-cat "OTHER-PLANT : " ?id " " ?dist " " ?idt) crlf)
	(retract ?t2)
)

(defrule MAP::remove-worse-plant-paths
	(declare (salience -5000))
	(machine-plant ?id ?idt ?dist)
	(not (run-away ?id "machine"))
	?m1 <- (move-place ?id "machine" ?dir ?hx1 ?hy1)
	?m2 <- (move-place ?id "machine" ?dir2 ?hx2 ?hy2)
	(map-object (id ?idt) (type "plant") (x ?xTo) (y ?yTo))
	(map-object (id ?id) (type "machine") (x ?x) (y ?y) (energy ?en))
	(test (< (distance ?xTo ?yTo ?hx1 ?hy1) (distance ?xTo ?yTo ?hx2 ?hy2)))
	=>
	;;(printout t (str-cat "WORSE-PATH : " ?dir2 " " ?id " " ?idt) crlf)
	;;(printout t (str-cat "OTHER-PATH : " ?dir " " ?id " " ?idt) crlf)
	(retract ?m2)
)

(defrule printer
(action (name ?n) (direction ?d) (type ?t) (id ?id))
;;(map-object (id ?id) (type "human") (x ?x) (y ?y) (energy ?en))
;;(map-object (id ?idt) (type "tree") (x ?xt) (y ?yt))
=>
	;;(printout t (str-cat "NEAR :" ?id " " ?idt " " (is-near ?x ?y ?xt ?yt) " " ?en) crlf)
;;(printout t (str-cat "ACTION : " ?n " " ?d " " ?s " " ?t " " ?id) crlf)
)